home *** CD-ROM | disk | FTP | other *** search
/ Programmer Power Tools / Programmer Power Tools.iso / pibterm / pibt41s4.arc / VIEWSUB1.MOD < prev    next >
Encoding:
Text File  |  1988-01-21  |  34.8 KB  |  784 lines

  1. (*----------------------------------------------------------------------*)
  2. (*             List_One_File --- List one file                          *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE List_One_File( View_File_Name : AnyStr );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*   Procedure:   List_One_File                                         *)
  10. (*                                                                      *)
  11. (*   Purpose:     Lists one file                                        *)
  12. (*                                                                      *)
  13. (*   Calling sequence:                                                  *)
  14. (*                                                                      *)
  15. (*      List_One_File( Dir_Entry : SearchRec );                         *)
  16. (*                                                                      *)
  17. (*         Dir_Entry --- Directory record of file to be listed.         *)
  18. (*                                                                      *)
  19. (*   Calls:  Init_This_File                                             *)
  20. (*           Display_Screen                                             *)
  21. (*           Prompt                                                     *)
  22. (*                                                                      *)
  23. (*   Remarks:                                                           *)
  24. (*                                                                      *)
  25. (*      This routine controls the listing of one file.                  *)
  26. (*                                                                      *)
  27. (*----------------------------------------------------------------------*)
  28.  
  29. CONST
  30.    Max_String    = 255        (* max string length             *);
  31.    FF            = #12        (* form feed character           *);
  32.    TAB           = #9         (* tab character                 *);
  33.    CR            = #13        (* carriage return character     *);
  34.    LF            = #10        (* line feed character           *);
  35.    ESC           = #27        (* escape character              *);
  36.    NUL           = #0         (* null character                *);
  37.  
  38. TYPE
  39.  
  40.    Line_Ptr = ^Line            (* pointer to text line           *);
  41.  
  42.    Line =                      (* text line                      *)
  43.       RECORD
  44.          Next: Line_Ptr        (* pointer to next line in buffer *);
  45.          Lnum: LONGINT         (* line number                    *);
  46.          Pnum: LONGINT         (* page number                    *);
  47.          Txt:  AnyStr          (* text Line                      *);
  48.       END;
  49.  
  50. VAR
  51.  
  52.    F            : TEXT               (* file to be listed                     *);
  53.    First        : Line_Ptr           (* pointer to first line in buffer       *);
  54.    Last         : Line_Ptr           (* pointer to last line in buffer,       *)
  55.                                      (* or nil if buffer empty                *);
  56.    PS_Size      : INTEGER            (* Physical screen size                  *);
  57.    Height       : INTEGER            (* List window height                    *);
  58.    Top          : Line_Ptr           (* pointer to top line in viewing window *);
  59.    Bot          : Line_Ptr           (* pointer to bottom line in viewing     *)
  60.                                      (* window                                *);
  61.    Cur_Line     : LONGINT            (* line number of next line on file f    *);
  62.    Max_Line     : LONGINT            (* max line number seen so far           *);
  63.    First_Col    : INTEGER            (* first col to be displayed             *);
  64.    Width        : INTEGER            (* screen width                          *);
  65.    Done         : BOOLEAN            (* TRUE when one file finished           *);
  66.    All_Done     : BOOLEAN            (* TRUE if all selected files listed     *);
  67.    Eod          : BOOLEAN            (* TRUE if requested line or page        *)
  68.                                      (* is beyond end of file f               *);
  69.    EOF_Seen     : BOOLEAN            (* TRUE if eof reached                   *);
  70.    Top_Line     : LONGINT            (* line number of top line on currently  *)
  71.                                      (* displayed screen                      *);
  72.    One_Up       : BOOLEAN            (* If command is move up one line        *);
  73.    One_Down     : BOOLEAN            (* If command is move down one line      *);
  74.  
  75.    Search_Str   : AnyStr             (* String to look for with search comm.  *);
  76.    Search_Lpos  : INTEGER            (* Screen position of line containing    *)
  77.                                      (* searched string                       *);
  78.    Search_Line  : LONGINT            (* Line number of line containing        *)
  79.                                      (* searched string                       *);
  80.    Search_Col   : INTEGER            (* Position of searched string in line   *);
  81.    Search_Exact : BOOLEAN            (* TRUE to do exact match in search      *);
  82.  
  83.                                      (* Unprintable characters                *)
  84.  
  85.    Spec_Chars   : ARRAY[CHAR] OF BOOLEAN;
  86.  
  87.    Strip_High   : BOOLEAN            (* TRUE to strip high-order bits         *);
  88.    Expand_Tabs  : BOOLEAN            (* TRUE to expand horizontal tabs        *);
  89.  
  90.    File_Spec    : AnyStr            (* Full path name of file being listed   *);
  91.    File_Pattern : AnyStr            (* Wildcard for files to list            *);
  92.    Dir_Entry    : SearchRec         (* Directory info for current file       *);
  93.  
  94.    Max_Buf_Lines     : INTEGER      (* Max number of lines in buffer *);
  95.  
  96.    Normal_Color      : INTEGER;
  97.    Search_Color      : INTEGER;
  98.    Status_Line_Color : INTEGER;
  99.    Spec_Chars_Color  : INTEGER;
  100.    Help_Text_Color   : INTEGER;
  101.    Spec_Chars_Color_2: INTEGER;
  102.  
  103. (*----------------------------------------------------------------------*)
  104. (*               Rmin --- Find minimum of two long integers             *)
  105. (*----------------------------------------------------------------------*)
  106.  
  107. FUNCTION Rmin( A, B: LONGINT ) : LONGINT;
  108.  
  109. (*----------------------------------------------------------------------*)
  110. (*                                                                      *)
  111. (*   Function: Rmin                                                     *)
  112. (*                                                                      *)
  113. (*   Purpose:  Returns smaller of two long integer numbers              *)
  114. (*                                                                      *)
  115. (*   Calling sequence:                                                  *)
  116. (*                                                                      *)
  117. (*      Smaller := RMIN( A , B : LONGINT ) : LONGINT;                   *)
  118. (*                                                                      *)
  119. (*         A       --- 1st input long integer number                    *)
  120. (*         B       --- 2nd input long integer number                    *)
  121. (*         Smaller --- smaller of A, B returned                         *)
  122. (*                                                                      *)
  123. (*                                                                      *)
  124. (*   Calls:  None                                                       *)
  125. (*                                                                      *)
  126. (*                                                                      *)
  127. (*----------------------------------------------------------------------*)
  128.  
  129. BEGIN (* Rmin *)
  130.  
  131.    IF A < B THEN
  132.       Rmin := A
  133.    ELSE
  134.       Rmin := B;
  135.  
  136. END   (* Rmin *);
  137.  
  138. (*----------------------------------------------------------------------*)
  139. (*               Rmax --- Find maximum of two long integers             *)
  140. (*----------------------------------------------------------------------*)
  141.  
  142. FUNCTION Rmax( A, B: LONGINT ) : LONGINT;
  143.  
  144. (*----------------------------------------------------------------------*)
  145. (*                                                                      *)
  146. (*   Function:  Rmax                                                    *)
  147. (*                                                                      *)
  148. (*   Purpose:   Returns larger of two long integer numbers              *)
  149. (*                                                                      *)
  150. (*   Calling sequence:                                                  *)
  151. (*                                                                      *)
  152. (*      Larger := RMAX( A , B : LONGINT ) : LONGINT;                    *)
  153. (*                                                                      *)
  154. (*         A       --- 1st input long integer number                    *)
  155. (*         B       --- 2nd input long integer number                    *)
  156. (*         Larger  --- Larger of A, B returned                          *)
  157. (*                                                                      *)
  158. (*                                                                      *)
  159. (*   Calls:  None                                                       *)
  160. (*                                                                      *)
  161. (*----------------------------------------------------------------------*)
  162.  
  163. BEGIN (* Rmax *)
  164.  
  165.    IF A > B THEN
  166.       Rmax := A
  167.    ELSE
  168.       Rmax := B;
  169.  
  170. END   (* Rmax *);
  171.  
  172. (*----------------------------------------------------------------------*)
  173. (*        Reset_F:  Reposition file to beginning of information         *)
  174. (*----------------------------------------------------------------------*)
  175.  
  176. PROCEDURE Reset_F;
  177.  
  178. (*----------------------------------------------------------------------*)
  179. (*                                                                      *)
  180. (*   Procedure:   Reset_F                                               *)
  181. (*                                                                      *)
  182. (*   Purpose:     Resets file being listed to beginning of information. *)
  183. (*                                                                      *)
  184. (*   Calling sequence:                                                  *)
  185. (*                                                                      *)
  186. (*      Reset_F;                                                        *)
  187. (*                                                                      *)
  188. (*   Calls:  Reset                                                      *)
  189. (*                                                                      *)
  190. (*   Remarks:                                                           *)
  191. (*                                                                      *)
  192. (*      Cur_Line is reset to 1 here.                                    *)
  193. (*                                                                      *)
  194. (*----------------------------------------------------------------------*)
  195.  
  196. BEGIN  (* Reset_F *)
  197.  
  198.    RESET( F );
  199.  
  200.    Cur_Line := 1;
  201.  
  202. END    (* Reset_F *);
  203.  
  204. (*----------------------------------------------------------------------*)
  205. (*                Readln_F:  Read a line from the file F                *)
  206. (*----------------------------------------------------------------------*)
  207.  
  208. PROCEDURE Readln_F;
  209.  
  210. (*----------------------------------------------------------------------*)
  211. (*                                                                      *)
  212. (*   Procedure:   Readln_F                                              *)
  213. (*                                                                      *)
  214. (*   Purpose:     Read a line from the file F                           *)
  215. (*                                                                      *)
  216. (*   Calling sequence:                                                  *)
  217. (*                                                                      *)
  218. (*      Readln_F;                                                       *)
  219. (*                                                                      *)
  220. (*   Calls:  None                                                       *)
  221. (*                                                                      *)
  222. (*   Remarks:                                                           *)
  223. (*                                                                      *)
  224. (*      EOF( F ) MUST be FALSE on entry, but may be TRUE on exit.       *)
  225. (*      Cur_Line and Max_Line are updated.                              *)
  226. (*                                                                      *)
  227. (*      Note:  The input buffer for file F is used to "peek" at         *)
  228. (*             the next character.  This corresponds to looking at      *)
  229. (*             F^ in standard Pascal.                                   *)
  230. (*                                                                      *)
  231. (*----------------------------------------------------------------------*)
  232.  
  233. BEGIN (* Readln_F *)
  234.                                    (* Reset F to beginning of next  *)
  235.                                    (* line.                         *)
  236.    IF ( NOT Strip_High ) THEN
  237.       READLN( F );
  238.                                    (* Update current line           *)
  239.    INC( Cur_Line );
  240.  
  241.    Max_Line := RMax( Cur_Line , Max_Line );
  242.  
  243. END   (* Readln_F *);
  244.  
  245. (*----------------------------------------------------------------------*)
  246. (*              Clear_Buffer -- Clears buffer of saved lines            *)
  247. (*----------------------------------------------------------------------*)
  248.  
  249. PROCEDURE Clear_Buffer;
  250.  
  251. (*----------------------------------------------------------------------*)
  252. (*                                                                      *)
  253. (*   Procedure:   Clear_Buffer                                          *)
  254. (*                                                                      *)
  255. (*   Purpose:     Clears buffer of saved lines.                         *)
  256. (*                                                                      *)
  257. (*   Calling sequence:                                                  *)
  258. (*                                                                      *)
  259. (*      Clear_Buffer;                                                   *)
  260. (*                                                                      *)
  261. (*   Calls:  None                                                       *)
  262. (*                                                                      *)
  263. (*----------------------------------------------------------------------*)
  264.  
  265. BEGIN  (* Clear_Buffer *)
  266.  
  267.    Last := NIL;
  268.  
  269. END    (* Clear_Buffer *);
  270.  
  271. (*----------------------------------------------------------------------*)
  272. (*              Skip_To_Line --- Skips to specified line in file F      *)
  273. (*----------------------------------------------------------------------*)
  274.  
  275. PROCEDURE Skip_To_Line( N : LONGINT );
  276.  
  277. (*----------------------------------------------------------------------*)
  278. (*                                                                      *)
  279. (*   Procedure:   Skip_To_Line                                          *)
  280. (*                                                                      *)
  281. (*   Purpose:     Skips forward to specified line on file F.            *)
  282. (*                                                                      *)
  283. (*   Calling sequence:                                                  *)
  284. (*                                                                      *)
  285. (*      Skip_To_Line( N : LONGINT );                                    *)
  286. (*                                                                      *)
  287. (*         N  --- line to skip to                                       *)
  288. (*                                                                      *)
  289. (*   Calls:  Readln_F                                                   *)
  290. (*                                                                      *)
  291. (*   Remarks:                                                           *)
  292. (*                                                                      *)
  293. (*      Line  N  must exist.  File F must also be positioned at or      *)
  294. (*      before line  N.  On exit file F is positioned at line  N.       *)
  295. (*                                                                      *)
  296. (*----------------------------------------------------------------------*)
  297.  
  298. BEGIN  (* Skip_To_Line *)
  299.  
  300.    WHILE ( Cur_Line < N ) DO
  301.       Readln_F;
  302.  
  303. END    (* Skip_To_Line *);
  304.  
  305. (*----------------------------------------------------------------------*)
  306. (*              Scan_To_EOF  -- Scan forward to end of file on F        *)
  307. (*----------------------------------------------------------------------*)
  308.  
  309. PROCEDURE Scan_To_EOF;
  310.  
  311. (*----------------------------------------------------------------------*)
  312. (*                                                                      *)
  313. (*   Procedure:   Scan_To_EOF                                           *)
  314. (*                                                                      *)
  315. (*   Purpose:     Skips forward to end of file on file F.               *)
  316. (*                                                                      *)
  317. (*   Calling sequence:                                                  *)
  318. (*                                                                      *)
  319. (*      Scan_To_EOF;                                                    *)
  320. (*                                                                      *)
  321. (*   Calls:  Readln_F                                                   *)
  322. (*           Reset_F                                                    *)
  323. (*                                                                      *)
  324. (*   Remarks:                                                           *)
  325. (*                                                                      *)
  326. (*      On entry EOF_Seen = FALSE.  On exit EOF_Seen = TRUE, Max_Line = *)
  327. (*      the largest line number on the file.  F is also reset on exit.  *)
  328. (*      This routine is called for large forward skips by the Find_Line *)
  329. (*      routine.  It is called AT MOST ONCE per viewing of a file.      *)
  330. (*                                                                      *)
  331. (*----------------------------------------------------------------------*)
  332.  
  333. BEGIN  (* Scan_To_EOF *)
  334.  
  335.    WHILE ( NOT EOF( F ) ) DO
  336.       Readln_F;
  337.  
  338.    EOF_Seen := TRUE;
  339.    Reset_F;
  340.  
  341. END    (* Scan_To_EOF *);
  342.  
  343. (*----------------------------------------------------------------------*)
  344. (*                  Read_Line --- read line from file F                 *)
  345. (*----------------------------------------------------------------------*)
  346.  
  347. PROCEDURE Read_Line;
  348.  
  349. (*----------------------------------------------------------------------*)
  350. (*                                                                      *)
  351. (*   Procedure:   Read_Line                                             *)
  352. (*                                                                      *)
  353. (*   Purpose:     Reads next line from file F and appends it to buffer. *)
  354. (*                                                                      *)
  355. (*   Calling sequence:                                                  *)
  356. (*                                                                      *)
  357. (*      Read_Line;                                                      *)
  358. (*                                                                      *)
  359. (*   Remarks:                                                           *)
  360. (*                                                                      *)
  361. (*     If the buffer is full the first Line in the buffer               *)
  362. (*     is deleted to make room.  This operation "slides the buffer      *)
  363. (*     forward" one line on the file.  If EOF(F)  is TRUE on entry      *)
  364. (*     then no line is read, and Eof_Seen is set TRUE.  Tabs are        *)
  365. (*     expanded, if Expands_Tabs is TRUE.  If the high-order bits are   *)
  366. (*     to be stripped then the read is done character by character to   *)
  367. (*     avoid problems with "disguised" carriage returns.   On entry F   *)
  368. (*     must be positioned at EOF or at the beginning of a line.  On     *)
  369. (*     exit F is left positioned at EOF or at the beginning of the next *)
  370. (*     line.                                                            *)
  371. (*                                                                      *)
  372. (*----------------------------------------------------------------------*)
  373.  
  374. VAR
  375.    Line:    STRING[Max_String];
  376.    Inlen:   INTEGER;
  377.    C:       CHAR;
  378.    I:       INTEGER;
  379.    J:       INTEGER;
  380.    N:       INTEGER;
  381.    LTxt:    INTEGER;
  382.  
  383. BEGIN (* Read_Line *)
  384.  
  385.    IF ( NOT EOF( F ) ) THEN
  386.       BEGIN
  387.                                    (* Figure position in line buffer *)
  388.          IF ( Last = NIL ) THEN
  389.             Last := First
  390.          ELSE
  391.             BEGIN
  392.                Last := Last^.Next;
  393.                IF ( Last = First ) THEN
  394.                   First := First^.Next
  395.             END;
  396.  
  397.          WITH Last^ DO
  398.             BEGIN
  399.                                    (* Remember line number of this line *)
  400.                Lnum := Cur_Line;
  401.                                    (* Get text of line.                 *)
  402.                                    (* If bit-stripping, check on a      *)
  403.                                    (* character by character basis for  *)
  404.                                    (* CR/LF combinations.               *)
  405.  
  406.                IF ( NOT Strip_High ) THEN
  407.                   READ( F , Txt )
  408.                ELSE
  409.                   BEGIN
  410.  
  411.                      Txt  := '';
  412.                      LTxt := 0;
  413.  
  414.                      READ( F , C );
  415.  
  416.                      C := CHR( ORD( C ) AND $7F );
  417.  
  418.                      WHILE ( C <> CR ) DO
  419.                         BEGIN
  420.                            INC( LTxt );
  421.                            Txt[LTxt] := C;
  422.                            READ( F , C );
  423.                            C  := CHR( ORD( C ) AND $7F );
  424.                         END;
  425.  
  426.                      READ( F , C );
  427.  
  428.                      Txt[0] := CHR( LTxt );
  429.  
  430.                   END;
  431.  
  432.                                    (* Expand tabs if requested          *)
  433.                IF Expand_Tabs THEN
  434.                   BEGIN
  435.  
  436.                      Line    := Txt;
  437.                      Txt     := '';
  438.                      LTxt    := 0;
  439.  
  440.                      Inlen   := LENGTH( Line );
  441.  
  442.                      I := 0;
  443.                      J := 0;
  444.  
  445.                      WHILE ( ( J < Inlen ) AND ( I < Max_String ) ) DO
  446.                         BEGIN
  447.  
  448.                            INC( J );
  449.  
  450.                            C := Line[J];
  451.  
  452.                            IF ( C = TAB ) THEN
  453.                               BEGIN
  454.  
  455.                                  N := 8 - ( I MOD 8 );
  456.  
  457.                                  WHILE ( I < Max_String ) AND ( N > 0 ) DO
  458.                                     BEGIN
  459.                                        INC(  I   );
  460.                                        INC( LTxt );
  461.                                        Txt[ LTxt ] := ' ';
  462.                                        DEC( N    );
  463.                                     END;
  464.  
  465.                               END
  466.                            ELSE
  467.                               BEGIN
  468.                                  INC( LTxt );
  469.                                  Txt[ LTxt ] := C;
  470.                               END;
  471.  
  472.                         END (* While *);
  473.  
  474.                      Txt[0] := CHR( LTxt );
  475.  
  476.                   END (* IF Expand_Tabs *);
  477.  
  478.             END  (* With Last^ *) ;
  479.  
  480.          Readln_F;
  481.  
  482.       END
  483.  
  484.    ELSE
  485.       Eof_Seen := TRUE;
  486.  
  487. END   (* Read_Line *);
  488.  
  489. (*----------------------------------------------------------------------*)
  490. (*                  Get_Search_String --- Get string to search for      *)
  491. (*----------------------------------------------------------------------*)
  492.  
  493. PROCEDURE Get_Search_String;
  494.  
  495. VAR
  496.    Local_Save : Saved_Screen_Ptr;
  497.  
  498. BEGIN (* Get_Search_String *)
  499.  
  500.    Search_Exact := FALSE;
  501.    Search_Lpos  := 0;
  502.    Search_Line  := 0;
  503.  
  504.    Draw_Titled_Box( Local_Save, 10, 10, 65, 14, 'Search for string');
  505.  
  506.    TextColor( Menu_Text_Color_2 );
  507.  
  508.    CursorOn;
  509.  
  510.    GoToXY( 1 , 1 );
  511.    WRITE('String to search for? ');
  512.  
  513.    TextColor( Menu_Text_Color );
  514.  
  515.    Read_Edited_String( Search_Str );
  516.  
  517.    IF ( NOT Search_Exact ) THEN
  518.       Search_Str := UpperCase( Search_Str );
  519.  
  520.    Restore_Screen( Local_Save );
  521.  
  522.    CursorOff;
  523.  
  524. END   (* Get_Search_String *);
  525.  
  526. (*----------------------------------------------------------------------*)
  527. (*                  Get_Line_Number --- Get line number to search for   *)
  528. (*----------------------------------------------------------------------*)
  529.  
  530. PROCEDURE Get_Line_Number( VAR LineNo : LONGINT );
  531.  
  532. VAR
  533.    Local_Save  : Saved_Screen_Ptr;
  534.    N           : LongInt;
  535.    B           : BOOLEAN;
  536.  
  537. BEGIN (* Get_Line_Number *)
  538.  
  539.    Draw_Titled_Box( Local_Save, 10, 10, 65, 14, 'Jump to line');
  540.  
  541.    TextColor( Menu_Text_Color_2 );
  542.  
  543.    CursorOn;
  544.  
  545.    GoToXY( 1 , 1 );
  546.    WRITE('Line number to jump to? ');
  547.  
  548.    TextColor( Menu_Text_Color );
  549.  
  550.    IF ( NOT Read_Number( 0, FALSE, LineNo ) ) THEN
  551.       LineNo := -1;
  552.  
  553.    Restore_Screen( Local_Save );
  554.  
  555.    CursorOff;
  556.  
  557. END   (* Get_Search *);
  558.  
  559. (*----------------------------------------------------------------------*)
  560. (*                  Find_Line --- Find line on file F                   *)
  561. (*----------------------------------------------------------------------*)
  562.  
  563. PROCEDURE Find_Line( N : LONGINT );
  564.  
  565. (*----------------------------------------------------------------------*)
  566. (*                                                                      *)
  567. (*   Procedure:   Find_Line                                             *)
  568. (*                                                                      *)
  569. (*   Purpose:     Finds and moves to specified line on file F           *)
  570. (*                                                                      *)
  571. (*   Calling sequence:                                                  *)
  572. (*                                                                      *)
  573. (*      Find_Line( N : LONGINT );                                       *)
  574. (*                                                                      *)
  575. (*         N --- line to be found                                       *)
  576. (*                                                                      *)
  577. (*   Calls:  Read_Line                                                  *)
  578. (*           RMIN                                                       *)
  579. (*           Clear_Buffer                                               *)
  580. (*           Skip_To_Line                                               *)
  581. (*           Reset_F                                                    *)
  582. (*           Scan_To_Eof                                                *)
  583. (*                                                                      *)
  584. (*   Remarks:                                                           *)
  585. (*                                                                      *)
  586. (*      On exit Eod=TRUE if the line does not exist.  In this case the  *)
  587. (*      buffer is full and it contains the lines at end of the file.    *)
  588. (*      Otherwise Eod=FALSE, line n is in the buffer, and top points    *)
  589. (*      to it.                                                          *)
  590. (*                                                                      *)
  591. (*      The algorithm divides into three cases.                         *)
  592. (*                                                                      *)
  593. (*      Case 1.  The line preceeds the buffer.  In this case the file   *)
  594. (*      is reset and the buffer is cleared.  The goal is to exit        *)
  595. (*      with the buffer full and with line n at the end of the buffer.  *)
  596. (*      This is accomplished by skipping the proper number of lines,    *)
  597. (*      then reading lines into the buffer until line n has been        *)
  598. (*      reached.                                                        *)
  599. (*                                                                      *)
  600. (*      Case 2.  The line is inside the buffer.  A simple linear search *)
  601. (*      of the buffer locates the requested line.                       *)
  602. (*                                                                      *)
  603. (*      Case 3.  The line follows the buffer.  This is the complicated  *)
  604. (*      case.  As in case 1, the goal is to exit with a full buffer     *)
  605. (*      and with line n at the end of the buffer.  However, if line n   *)
  606. (*      does not exist then we want to exit with a full buffer          *)
  607. (*      consisting of the lines at the end of the file.  For efficiency *)
  608. (*      in large forward skips, we don't want to simply read lines into *)
  609. (*      the buffer until line n or eof is encountered.  Skipping is     *)
  610. (*      faster than reading, so we'd prefer to skip lines, then read a  *)
  611. (*      full buffer's worth.  The problem is to determine how many      *)
  612. (*      lines to skip.                                                  *)
  613. (*                                                                      *)
  614. (*      (a) If line n is within Max_Buf_Lines of the Last line in the   *)
  615. (*          buffer then no lines are skipped.  Lines are simply read    *)
  616. (*          into the buffer until line n or eof is reached.  This is    *)
  617. (*          a "short" forwards skip.                                    *)
  618. (*                                                                      *)
  619. (*      (b) Assume (a) doesn't hold.  If n is less than or equal to the *)
  620. (*          maximum line number seen so far then we know that line n    *)
  621. (*          must exist.  In this case we skip to line (n-Max_Buf_Lines),*)
  622. (*          then read lines into the buffer until line n is reached.    *)
  623. (*                                                                      *)
  624. (*      (c) Assume neither (a) nor (b) holds.  If we have earlier       *)
  625. (*          encountered eof on file f, then Max_Line is the largest     *)
  626. (*          line number on the file, and we know whether or not line    *)
  627. (*          n exists.  In this case we skip to line min(n,Max_Line) -   *)
  628. (*          Max_Buf_Lines, and then read lines into the buffer until    *)
  629. (*          either line n or eof is reached.                            *)
  630. (*                                                                      *)
  631. (*      (d) If none of cases (a), (b) or (c) hold then we scan to       *)
  632. (*          eof to determine whether or not line n exists.  Max_Line    *)
  633. (*          is now the largest line number on the file.  File f is      *)
  634. (*          reset, and we proceed as in case (c).  Note that this case  *)
  635. (*          can occur at most once per run of the viewer.               *)
  636. (*                                                                      *)
  637. (*----------------------------------------------------------------------*)
  638.  
  639. VAR
  640.    M : LONGINT;
  641.  
  642. BEGIN  (* Find_Line *)
  643.  
  644.    Eod := FALSE;
  645.                                    (* Case 1 *)
  646.    IF ( N < First^.LNum ) THEN
  647.       BEGIN
  648.  
  649.          Reset_F;
  650.  
  651.          Clear_Buffer;
  652.  
  653.          IF ( N > Max_Buf_Lines ) THEN
  654.             Skip_To_Line( N - Max_Buf_Lines );
  655.  
  656.          REPEAT
  657.             Read_Line;
  658.          UNTIL ( Last^.LNum = N );
  659.  
  660.          Top := Last;
  661.  
  662.       END                          (* Case 2 *)
  663.    ELSE IF ( N <= Last^.LNum ) THEN
  664.       BEGIN
  665.  
  666.          Top := First;
  667.  
  668.          WHILE ( Top^.LNum < N ) DO Top := Top^.Next;
  669.  
  670.       END
  671.    ELSE
  672.       BEGIN                        (* Case 3 *)
  673.  
  674.          IF ( ( NOT EOF_Seen ) AND ( ( N - Max_Buf_Lines ) > Last^.LNum )
  675.             AND ( N > Max_Line ) ) THEN
  676.                Scan_To_Eof;
  677.  
  678.          M := RMIN( N , Max_Line ) - Max_Buf_Lines;
  679.  
  680.          IF ( M > Last^.LNum ) THEN
  681.             BEGIN
  682.                Clear_Buffer;
  683.                Skip_To_Line( M )
  684.             END;
  685.  
  686.          REPEAT
  687.             Read_Line;
  688.          UNTIL ( ( Last^.LNum = N ) OR EOF( F ) );
  689.  
  690.          Top := Last;
  691.          Eod := ( Top^.LNum < N );
  692.  
  693.       END;
  694.  
  695. END   (* Find_Line *);
  696.  
  697. (*----------------------------------------------------------------------*)
  698. (*           Find_String --- Find next occurrence of string on F        *)
  699. (*----------------------------------------------------------------------*)
  700.  
  701. PROCEDURE Find_String( S: AnyStr );
  702.  
  703. (*----------------------------------------------------------------------*)
  704. (*                                                                      *)
  705. (*   Procedure:   Find_String                                           *)
  706. (*                                                                      *)
  707. (*   Purpose:     Find next occurrence of string on F                   *)
  708. (*                                                                      *)
  709. (*   Calling sequence:                                                  *)
  710. (*                                                                      *)
  711. (*      Find_String( S: AnyStr );                                       *)
  712. (*                                                                      *)
  713. (*         S --- String to be found                                     *)
  714. (*                                                                      *)
  715. (*   Calls:  Read_Line                                                  *)
  716. (*           Find_Line                                                  *)
  717. (*                                                                      *)
  718. (*----------------------------------------------------------------------*)
  719.  
  720. VAR
  721.    Found:  BOOLEAN;
  722.    Done:   BOOLEAN;
  723.    LineNo: INTEGER;
  724.    N:      INTEGER;
  725.  
  726. LABEL 1;
  727.  
  728. BEGIN  (* Find_String *)
  729.  
  730.    Found       := FALSE;
  731.    Done        := FALSE;
  732.  
  733.    Search_Lpos := 0;
  734.    Search_Col  := 0;
  735.  
  736.    REPEAT
  737.  
  738.       Bot    := Top;
  739.       LineNo := 0;
  740.       N      := Height;
  741.  
  742.       WHILE ( ( N > 0 ) AND ( NOT Eod ) ) DO
  743.          BEGIN
  744.  
  745.             INC( LineNo );
  746.  
  747.             IF Search_Exact THEN
  748.                Search_Col := POS( Search_Str , Bot^.Txt )
  749.             ELSE
  750.                Search_Col := POS( Search_Str , UpperCase( Bot^.Txt ) );
  751.  
  752.             IF ( Search_Col <> 0 ) THEN
  753.                BEGIN
  754.                   Search_Lpos := LineNo;
  755.                   Search_Line := Bot^.Lnum;
  756.                   Found       := TRUE;
  757.                   GOTO 1;
  758.                END;
  759.  
  760.             DEC( N );
  761.  
  762.             IF ( N > 0 ) THEN
  763.                IF ( Bot = Last ) THEN
  764.                   BEGIN
  765.                      Read_Line;
  766.                      Eod := EOF( F );
  767.                      Bot := Last;
  768.                   END
  769.                ELSE
  770.                   Bot := Bot^.Next;
  771.  
  772.          END;
  773.  
  774.       Done := ( N > 0 );
  775.  
  776.       IF ( NOT Done ) THEN
  777.          Find_Line( Top^.LNum + Height );
  778.  
  779. 1:
  780.    UNTIL ( Found OR Done );
  781.  
  782. END    (* Find_String *);
  783.  
  784.